﻿
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WHControlLib.Controls
{
    //[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
    public partial class WHPanel : /*UserControl */Panel
    {
        public WHPanel()
        {       //设置双缓冲

            this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                     ControlStyles.ResizeRedraw |
                     ControlStyles.AllPaintingInWmPaint, true);

            ////背景定义为透明色   
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.BackColor = Color.Transparent;




            InitializeComponent();
        

        }

        //全局定义

        /// <summary>
        /// 控件整体的矩形大小
        /// </summary>
        public Rectangle MyRect = new Rectangle();
        /// <summary>
        /// 需要画出控件的矩形大小因为控件本身是透明色，为了消除锯齿现象所以画出的控件 小于 本控件的实际大小。
        /// </summary>
        public Rectangle DrawRect = new Rectangle();



      float HBL = 1.00f;
        float VBl = 1.00f;




        #region 属性定义
        public int OldWidth { get; set; }
        public int OldHeight { get; set; }
        public int OldLeft { get; set; }
        public int OldTop { get; set; }
        public enum FillColorDec
        {
            Vertical,
            Horizontal,
            LeftVH,
            RightVH

        }

        public enum TextAlign
        {
            CenterMiddle, CenterLeft, CenterRight, CenterButtom, CenterTop, TopLeft, TopRight, BottomLeft, BottomRight
        }



        private bool _isUseSYSStyle;
        [Category("A我的"), Description("是否使用系统样式，不适用自定义样式，仅仅开启双缓冲，默认，false"), Browsable(true)]
        public bool IsUseSYSStyle
        {
            get { return _isUseSYSStyle; }
            set { _isUseSYSStyle = value; }
        }



        private FillColorDec _myFillColorDec=FillColorDec.Vertical;
        [Category("A我的"), Description("当启用渐变色时的渐变方向，默认，垂直方向"), Browsable(true)]
        public FillColorDec MyFillColorDec
        {
            get { return _myFillColorDec; }
            set { _myFillColorDec = value; Invalidate(); }
        }
        //目前此功能效果一般，因有比例误差的原因，和 控件 自带锚点和Dock属性相互制约等影响，运行其期凑活
        
        private bool _isZoom;
        [Category("A我的"), Description("是否对内部控件自动随本容器缩放,设计期连续改变容器大小效果不好，运行期因有比例误差不可连续缩放，也可不启用，用dock，Anthor用户手工代替，默认，false"), Browsable(true)]
        public bool IsZoom
        {
            get { return _isZoom; }
            set { _isZoom = value; }
        }


        private bool _isShowBorder = true;
        [Category("A我的"), Description("是否显示控件外边框，默认，true"), Browsable(true)]
        public bool IsShowBorder
        {
            get { return _isShowBorder; }
            set { _isShowBorder = value; Invalidate(); }

        }
        private Color _unEnableColor = Color.Gray;
        [Category("A我的"), Description("当不可用时候的颜色，默认，灰色"), Browsable(true)]
        public Color UnEnableColor
        {
            get { return _unEnableColor; }
            set { _unEnableColor = value; Invalidate(); }
        }
        private Color _borderColor = Color.Blue;
        /// <summary>
        /// 边框颜色
        /// </summary>
        [Category("A我的"), Description("边框颜色"), Browsable(true)]
        public Color BorderColor
        {
            get { return _borderColor; }
            set { _borderColor = value; this.Invalidate(); }
        }

        private float _borderWidth = 2;
        [Category("A我的"), Description("边框的宽度，默认 2"), Browsable(true)]
        public float BorderWidth
        {
            get { return _borderWidth; }
            set { _borderWidth = value; Invalidate(); }
        }
        private bool _isUseTwoColor;
        [Category("A我的"), Description("是否启用两种颜色填充，默认 false"), Browsable(true)]
        public bool IsUseTwoColor
        {
            get { return _isUseTwoColor; }
            set { _isUseTwoColor = value; Invalidate(); }
        }
        /// <summary>
        /// 第一种背景填充色
        /// </summary>
        private Color _firstFillcolor = Color.Orange;
        [Category("A我的"), Description(" 第一种背景填充色"), Browsable(true)]
        public Color FirstFillcolor
        {
            get { return _firstFillcolor; }
            set
            {
                _firstFillcolor = value;

                this.Invalidate();
            }
        }
        private Color _secondFillcolor = Color.Orange;
        [Category("A我的"), Description(" 第二种背景填充色"), Browsable(true)]
        public Color SecondFillcolor
        {
            get { return _secondFillcolor; }
            set
            {
                _secondFillcolor = value;

                this.Invalidate();
            }
        }

        private Color fontColor = Color.Black;
        [Category("A我的"), Description(" 字体颜色，默认黑色"), Browsable(true)]
        public Color FontColor
        {
            get { return fontColor; }
            set { fontColor = value; this.Invalidate(); }
        }

        private Font _myFont = new Font("微软雅黑", 12.0f, 0, GraphicsUnit.Point, 1);
        [Category("A我的"), Description(" 控件字体，默认 微软雅黑12t"), Browsable(true)]
        public Font MyFont
        {
            get { return _myFont; }
            set { _myFont = value; this.Invalidate(); }
        }


        ////当用隐藏的Text属性时必须这么加特性才能使本控件使用
        [Category("A我的"), Description("文字在控件上显示文字，默认"), Browsable(true)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get => base.Text;
            set
            {
                base.Text = value;
                Invalidate();
            }
        }

        private TextAlign _myTextAlign = TextAlign.CenterMiddle;
        [Category("A我的"), Description("文字在控件上显示的对齐方式，默认，中间对齐"), Browsable(true)]
        public virtual TextAlign MyTextAlign
        {
            get { return _myTextAlign; }
            set { _myTextAlign = value; Invalidate(); }
        }

        //**********************
        public enum ShowRadiusDes
        {
            All, Top, Buttom, None
        }
        private ShowRadiusDes _myShowRadiusDes = ShowRadiusDes.All;
        [Category("A我的"), Description(" 哪里显示圆角，默认All都显示"), Browsable(true)]
        public ShowRadiusDes MyShowRadiusDes
        {
            get => _myShowRadiusDes;
            set { _myShowRadiusDes = value; Invalidate(); }
        }
        private float radius = 7.0f;

        /// <summary>
        /// 圆角大小比例
        /// </summary>
        [Category("A我的"), Description(" 圆角大小比例默认7.0,值越大圆角比例越小,标题栏高度跟随其变化，不能小于1.1"), Browsable(true)]
        public float Radius
        {
            get => radius;
            set
            {
                if (value > 1.1f)
                {
                    radius = value;
                    Invalidate();
                }
                else { radius = 1.1f; Invalidate(); }

            }
        }

        #endregion
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            OldHeight = this.Height;
            OldWidth = this.Width;
            OldTop = this.Top;
            OldLeft = this.Left;
        }





        void BeginPainIni()
        {
            MyRect = this.ClientRectangle;


            //DrawRect.X = MyRect.X + BorderWidth / 2;
            //DrawRect.Y = MyRect.Y + BorderWidth / 2;
            //DrawRect.Width = MyRect.Width - BorderWidth;
            //DrawRect.Height = MyRect.Height - BorderWidth;

            OldHeight = this.Height;
            OldWidth = this.Width;
            OldTop = this.Top;
            OldLeft = this.Left;

        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

           Graphics Myg = e.Graphics;
            Myg.SmoothingMode = SmoothingMode.AntiAlias;
            Myg.CompositingQuality = CompositingQuality.HighQuality;
            Myg.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //简单模式
            if (IsUseSYSStyle)
            {
                SamplePain(Myg);



                return;
            }
           
            BeginPainIni();

          

            //////////画形状并填充

            DrawAndFillShape(Myg, GetCtrlShapePath( MyRect));

            //isCanZoom();


            ////////画标尺刻度此处为了方便预留该过程
            DrawRuler(Myg);

        }
      /// <summary>
      /// 画标尺刻度该处预留，不实现让子类实现
      /// </summary>
        public virtual void DrawRuler(Graphics Myg )
           
        {

        }
        public GraphicsPath GetMyBodyPath(Rectangle MYRect, float BorderWidth, float Radius)
        {
            GraphicsPath path = new GraphicsPath();
            float PenWidth = BorderWidth / 2;
            float HWheight = MYRect.Height / Radius;
            //定义四角小正方形的长度  这里不减一半线宽会发现画外边框两边的对不齐
            float w = HWheight - BorderWidth;
            float Pw = HWheight / 2;
            //当不显示圆角时候的矩形
            Rectangle NonedrawRect = new Rectangle();
            NonedrawRect.X = (int)(MyRect.X + PenWidth);
            NonedrawRect.Y = (int)(MyRect.Y + PenWidth);
            NonedrawRect.Width = (int)(MyRect.Width - BorderWidth);
            NonedrawRect.Height = (int)(MyRect.Height - BorderWidth);
            //当显示圆角时候的形状定义
            RectangleF topLeftRect = new RectangleF(MYRect.X + PenWidth, MYRect.Y + PenWidth, HWheight, HWheight);
            RectangleF topRightRect = new RectangleF(MYRect.X + MYRect.Width - HWheight - PenWidth, topLeftRect.Y, HWheight, HWheight);
            RectangleF bottomLeftRect = new RectangleF(topLeftRect.X, MYRect.Y + MYRect.Height - HWheight - PenWidth, HWheight, HWheight);
            RectangleF bottomRightRect = new RectangleF(MyRect.X + Width - HWheight - PenWidth, bottomLeftRect.Y, HWheight, HWheight);

            //12个点
            PointF leftTop = new PointF(MYRect.X + PenWidth, MYRect.Y + PenWidth);
            PointF leftTopLeft = new PointF(MYRect.X + PenWidth, MYRect.Y + PenWidth + Pw);
            PointF LeftTopRight = new PointF(MYRect.X + PenWidth + Pw, MYRect.Y + PenWidth);
            PointF Leftbuttom = new PointF(MYRect.X + PenWidth, MYRect.Y + MYRect.Height - PenWidth);
            PointF rightTop = new PointF(MYRect.X + MYRect.Width - PenWidth, MYRect.Y + PenWidth);
            PointF rightTopRight = new PointF(MYRect.X + MYRect.Width - PenWidth, MYRect.Y + PenWidth + Pw);
            PointF rightTopLeft = new PointF(MYRect.X + MYRect.Width - PenWidth - Pw, MYRect.Y + PenWidth);
            PointF rightbuttom = new PointF(MYRect.X + MYRect.Width - PenWidth, MYRect.Y + MYRect.Height - PenWidth);
            PointF LeftbuttomLeft = new PointF(MYRect.X + MYRect.Width - PenWidth - Pw, MYRect.Y + MYRect.Height - PenWidth);
            PointF LeftbuttomRight = new PointF(MYRect.X + PenWidth + Pw, MYRect.Y + MYRect.Height - PenWidth);
            PointF rightbuttomRight = new PointF(MYRect.X + MYRect.Width - PenWidth, MYRect.Y + MYRect.Height - PenWidth - Pw);
            PointF rightbuttomLeft = new PointF(MYRect.X + MYRect.Width - PenWidth - Pw, MYRect.Y + MYRect.Height - PenWidth);
            path.ClearMarkers();
            switch (MyShowRadiusDes)
            {
                case ShowRadiusDes.All:
                    path.AddArc(topLeftRect, 180, 90);
                    path.AddArc(topRightRect, 270, 90);
                    path.AddArc(bottomRightRect, 0, 90);
                    path.AddArc(bottomLeftRect, 90, 90);
                    path.CloseAllFigures();

                    break;
                case ShowRadiusDes.Top:
                    path.AddArc(topLeftRect, 180, 90);
                    path.AddArc(topRightRect, 270, 90);

                    path.AddLine(rightbuttom, Leftbuttom);
                    path.AddLine(Leftbuttom, leftTopLeft);
                    path.CloseAllFigures();

                    break;
                case ShowRadiusDes.Buttom:
                    path.AddArc(bottomRightRect, 0, 90);
                    path.AddArc(bottomLeftRect, 90, 90);
                    path.AddLine(leftTop, rightTop);
                    path.AddLine(rightTopRight, rightbuttomRight);
                    path.CloseAllFigures();


                    break;
                case ShowRadiusDes.None:
                    path.AddRectangle(NonedrawRect);

                    break;
                default:
                    path.AddRectangle(NonedrawRect);

                    break;
            }

            return path;



        }


        /// <summary>
        /// 得到控件的外形，如果子类需要改变外形重写此方法
        /// </summary>
        /// <param name="MyRect">外形的外接矩形</param>
        /// <returns>需要填充的形状</returns>
        public virtual GraphicsPath GetCtrlShapePath(Rectangle MyRect)
        {
            GraphicsPath myPath = new GraphicsPath();
           //如果不要圆角矩形
            //myPath.AddRectangle(MyRect);
           //目前实现了四个角是否是圆角
            myPath = GetMyBodyPath(MyRect, BorderWidth, Radius);

            return myPath;
        }
    public virtual void DrawAndFillShape(Graphics Myg, GraphicsPath myPath)
        {
            //当是可用状态时候
            if (Enabled)
            {
                //当启用渐变色显示
                if (IsUseTwoColor)
                {
                    LinearGradientBrush FillBrush;

                    switch (MyFillColorDec)
                    {
                        case FillColorDec.Vertical:

                            FillBrush = new LinearGradientBrush(MyRect, FirstFillcolor, SecondFillcolor, LinearGradientMode.Vertical);
                            break;
                        case FillColorDec.Horizontal:

                            FillBrush = new LinearGradientBrush(MyRect, FirstFillcolor, SecondFillcolor, LinearGradientMode.Horizontal);
                            break;
                        case FillColorDec.LeftVH:

                            FillBrush = new LinearGradientBrush(MyRect, FirstFillcolor, SecondFillcolor, LinearGradientMode.ForwardDiagonal);
                            break;

                        case FillColorDec.RightVH:

                            FillBrush = new LinearGradientBrush(MyRect, FirstFillcolor, SecondFillcolor, LinearGradientMode.BackwardDiagonal);
                            break;
                        default:

                            FillBrush = new LinearGradientBrush(MyRect, FirstFillcolor, SecondFillcolor, LinearGradientMode.Vertical);
                            break;
                    }

                    Myg.FillPath(FillBrush, myPath);
                    //释放资源
                    FillBrush.Dispose();

                }
                //不起用渐变色显示
                else
                {
                    using (SolidBrush backBrush = new SolidBrush(FirstFillcolor))
                    {
                        Myg.FillPath(backBrush, myPath);
                    }
                }
            }
            //当不可用状态时候
            else
            {
                using (SolidBrush backBrush = new SolidBrush(UnEnableColor))
                {
                    Myg.FillPath(backBrush, myPath);
                }
            }
            //如果画边框
            if (IsShowBorder)
            {
                using (Pen borderPen = new Pen(BorderColor, BorderWidth))
                {
                    Myg.DrawPath(borderPen, myPath);
                }

            }
        }


        public virtual void IfZoom(Control Myctrl)
        {
            foreach (var ctrl in Myctrl.Controls)
            {
                if (ctrl is Control)
                {
                    Control SCtrl = (Control)ctrl;
                
                      SCtrl.Width = (int) (SCtrl.Width * HBL);
                    SCtrl.Height = (int) (SCtrl.Height * VBl);
                    SCtrl.Top = (int)(SCtrl.Top * VBl);
                    SCtrl.Left = (int)(SCtrl.Left * HBL);


                    if (SCtrl.Controls.Count>0)
                    {  IfZoom(SCtrl);
                       
                    }
             
                }
            }
        }

        public virtual void StartZoom()
        {
            int NowWidth = Width;
            int NowHeight = this.Height;
            HBL =(float)NowWidth / OldWidth ;
            VBl = (float)NowHeight / OldHeight;
     
                try
                {
                    IfZoom(this);
                }
                catch (Exception)
                {

                    //throw;
                }

           


        }
       /// <summary>
       /// 简单填充模式，本控件之做容器的情况下
       /// </summary>
       /// <param name="Myg"></param>
        void SamplePain(Graphics Myg)

        {

            if (Enabled)
            {
                using (SolidBrush backBrush = new SolidBrush(FirstFillcolor))
                {
                    Myg.FillRectangle(backBrush, this.ClientRectangle);
                }

            }
            else
            {
                using (SolidBrush backBrush = new SolidBrush(UnEnableColor))
                {
                    Myg.FillRectangle(backBrush, this.ClientRectangle);
               
                }

            }

            //如果画边框
            if (IsShowBorder)
            {
                using (Pen borderPen = new Pen(BorderColor, BorderWidth))
                {
                  
                    Myg.DrawRectangle(borderPen, this.ClientRectangle);
                }


            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            if (IsZoom)
            {
                StartZoom();
            }


            OldHeight = this.Height;
            OldWidth = this.Width;
            OldTop = this.Top;
            OldLeft = this.Left;

            base.OnSizeChanged(e);
        }

    }
}
